<template>
  <el-select v-model="state.value" filterable clearable :multiple="props.multiple" placeholder="请选择" @change="onSelectChange" v-bind="$attrs">
    <el-option v-for="item in state.optionList" :key="item.value" :label="item.label" :value="item.value" />
  </el-select>
</template>

<script setup lang="ts">
  import { reactive, onMounted, watch } from 'vue'
  import request from '@/service'
  import { Ui } from '@/utils'
  import { isPlainObject } from 'xe-utils'

  const model = defineModel<any>({ required: true })

  const props = defineProps({
    transfer: {
      type: Boolean,
      default: true
    },
    multiple: {
      type: Boolean,
      default: false
    },
    optionList: {
      type: Array,
      default() {
        return []
      }
    },
    optionApi: {
      type: String,
      default: ''
    },
    queryParams: {
      type: Object,
      default: () => ({})
    },
    label: {
      type: String,
      default: 'name'
    },
    value: {
      type: String,
      default: 'id'
    }
  })

  interface IState {
    optionList: any[]
    value: string | any[]
  }

  const state = reactive<IState>({
    optionList: [],
    value: props.multiple ? [] : ''
  })

  /**----------------------------methods----------------------------------------------------------------------- */

  watch(
    () => props.optionList.length,
    () => {
      const { optionList } = props
      if (optionList.length && !state.optionList.length) return (state.optionList = refactorList(optionList))
    }
  )

  watch(
    model,
    () => {
      if (props.multiple && !model.value?.length) {
        state.value = []
      }
      if (!props.multiple && !model.value) {
        state.value = ''
      }

      if (model.value) {
        state.value = model.value
      }
    },
    {
      immediate: true
    }
  )

  const onSelectChange = () => {
    if (!props.transfer) return (model.value = state.value)
    if (props.multiple) {
      model.value = (state.value as any[]).join(',')
    } else {
      model.value = state.value as string
    }
  }

  /**
   * 重构列表
   * @param list 下拉列表
   */
  const refactorList = (list: any[]) => {
    const { label, value } = props
    const mapList = list.map(item => {
      if (isPlainObject(item)) {
        return {
          // @ts-ignore
          label: item[label],
          // @ts-ignore
          value: item[value]
        }
      }
      return {
        label: item,
        value: item
      }
    })

    initValue()

    return mapList
  }

  /**
   * 初始化model值
   */
  const initValue = () => {
    if (!props.transfer) return (state.value = model.value)

    if (props.multiple && model.value?.length) {
      state.value = (model.value as string).split(',')
    }

    if (!props.multiple && model.value) {
      state.value = model.value
    }
  }

  /**
   * 查询列表
   */
  const query = () => {
    const { optionApi, optionList } = props
    if (optionList.length && !state.optionList.length) return (state.optionList = refactorList(optionList))

    if (!optionApi) return

    request.get(props.optionApi, props.queryParams).then(res => {
      if (res.code !== 0) return Ui.useMessage('error', res.msg)

      if (res.data.records && res.data.records.length) {
        state.optionList = refactorList(res.data.records)
      } else if (res.data && res.data.length) {
        state.optionList = refactorList(res.data)
      }
    })
  }

  /**----------------------------lifecycle----------------------------------------------------------------------- */

  onMounted(() => {
    query()
  })
</script>

<style scoped></style>
